home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 06 - 1990 / 06.08 Aug 90 / OOP in HC Source / WN⁄OOP in HC Listings < prev   
Encoding:
Text File  |  1989-10-20  |  23.3 KB  |  577 lines  |  [TEXT/nX^n]

  1. Listing 1
  2. To build a pop-up menu field:
  3.  
  4. 1) create a card field
  5. 2) put the name you want the user to see in line 1
  6. 3) put these scripts into the fields scripts
  7. 4) type "menuitems" into line 3
  8. 5) resize the field so only the first line is showing
  9. 6) set the locktext of the field to true
  10.  
  11. Note:  If you use a script where the user level has been set so that the menu option for "new field" is not available you should insert the set user level commands at the places marked in the scripts.  This is necessary only for the HyperCard™ only version.
  12. ------------------------------------------------------------
  13. --FUNCTIONS & HANDLERS FROM THE "POP UP MENU CLASS
  14. on mousedown
  15.   --OVERRIDE:POPUP MENU: This is the mousedown handler for the pop-up
  16.   --menu class.  Holding the mouse down on the field gives the user defined
  17.   --pop-up menu.  Holding the mouse and option key down gives a menu to
  18.   --change the values of the instance variables. Holding the mouse and
  19.   --shift key down gives a menu of the messages (methods) that the
  20.   --instance can handle.
  21.   put 0 into cmdflag
  22.   --Let the user know something is going on
  23.   set the cursor to watch
  24.   --This gives the user a menu of the instance variables and lets the user change   
  25.   --them
  26.   if the optionkey is down then
  27.     put 1 into cmdflag
  28.     put instancelistmenu() into list
  29.     --This gives the user a menu of the instance methods (message handlers)
  30.     --and lets the user execute them
  31.   else if the shiftkey is down then
  32.     put 2 into cmdflag
  33.     put methodlistmenu() into list
  34.     --This gives the pop-up menu of options the user has specified
  35.   else
  36.     put getinstanceval(menuitems,line 2 of me) into list
  37.   end if
  38.   put the clickloc into loc
  39.   --Change the cursor for the user's selection of a menu option
  40.   set the cursor to arrow
  41.   put popmenu(list,loc) into itemchosen
  42.   --Let the user know something is happening
  43.   set the cursor to watch
  44.   --The last item in the list is the cancel option
  45.   if itemchosen > 0 and itemchosen is not the number of items in list ¬
  46.   then
  47.     if cmdflag = 0 then
  48.       handlemenu itemchosen,list
  49.     else if cmdflag= 1 then
  50.       executeinstancelistmenu itemchosen,list
  51.     else if cmdflag=2 then
  52.       executemethodmenu itemchosen,list
  53.     end if
  54.   end if
  55. end mousedown
  56.  
  57. on handlemenu itemchosen, list
  58.   --this handler is what you customize to take action based on which
  59.   -- menu option the user chooses.  It is not called if the user selects
  60.   -- the cancel option.
  61.   --  if you've set up the menu items as handlers in the class methods
  62.   -- then this script will work
  63.   send (item itemchosen of list) to me
  64. end handlemenu
  65.  
  66. on test
  67.   --This is just a test to show that the menu works.  For every menu
  68.   --item you should have a handler somewhere in the inheritance chain
  69.   --(field, card, background, stack, home) to handle the message
  70.   put "see it works" into message
  71. end test
  72. ------------------------------------------------------------------------------------------------
  73. --FUNCTIONS AND HANDLERS FROM THE "EXPORT" CLASS
  74.  
  75. function getinstancelist classname
  76.   --OVERRIDE:CLASS EXPORT:THIS OVERRIDES THE STANDARD   
  77.   --GETINSTANCELIST IN THE OBJECT CLASS IN ORDER TO ALLOW CLASS 
  78.   --INSTANCES TO BE EXPORTED.IN AN EXPORTED FIELD THE INSTANCE 
  79.   --VARIABLE NAMES ARE IN THE LAST LINE OF THE FIELD
  80.   -- this returns the instance list for a given classname  The item number in the    
  81.   -- instance list is 2 less than the
  82.   -- line number of the instance variable in the field
  83.   put empty into instancelist
  84.   if classname is not line 2 of me then
  85.     return "error"
  86.   else
  87.     return line (the number of lines in me) of me
  88.   end if
  89. end getinstancelist
  90. ------------------------------------------------------------------------------------------------
  91. --FUNCTIONS & HANDLERS FROM THE ROOT CLASS OBJECTS
  92.  
  93. on executeinstancelistmenu hit,list
  94.   --input number of item selected from instance list,instance list
  95.   --This lets the user change the value of instance variables
  96.   put word 3 to (the number of words in item hit of list) of list into¬
  97.   temp
  98.   ask "Enter value for " & temp with line hit +2 of me
  99.   if it is not empty then
  100.     put it into line hit+2 of me
  101.   end if
  102. end executeinstancelistmenu
  103.  
  104. on executemethodmenu hit,list
  105.   --input number of item selected from method list,method list
  106.   --this just sends the selected message to the instances
  107.   send (item hit of list) to me
  108. end executemethodmenu
  109.  
  110. function instancelistmenu
  111.   --output the instance list
  112.   put getinstancelist (line 2 of me) into temp
  113.   put the number of items in temp into numinstancevars
  114.   put empty into list
  115.   repeat with x=1 to numinstancevars
  116.     put "Set the " & item 1 of item x of temp into item x of list
  117.   end repeat
  118.   put ",Cancel" after list
  119.   return list
  120. end instancelistmenu
  121.  
  122. function methodlistmenu
  123.   --output the method list
  124.   put getinstancehandlernames(the short name of me) into temp
  125.   repeat with i=2 to the number of lines in temp
  126.     put line i of temp into item i-1 of list
  127.   end repeat
  128.   put ",Cancel" after list
  129.   return list
  130. end methodlistmenu
  131.  
  132. function popmenu list,loc
  133.   -- input: list of options,location of menu
  134.   -- output: number of menu item picked 0 if none or cancel
  135.   -- this takes a list of options,and a menu location and displays
  136.   -- a menu.  It also checks to see if the user picks the cancel option
  137.   if the number of items in list < 1 then
  138.     put "Cancel" into list
  139.   end if
  140.   put ((the number of items in list) + 10) into nlist
  141.   put redolist (list) into list
  142.   put item 1 of  loc+50 into h
  143.   put item 2 of  loc+50 into v
  144.   --This is Andrew Gilmartin's XFCN
  145.   get PopUpMenu(list,nlist, v, h)
  146.   --This is message to let the user know that he has to hold the mouse
  147.   --down on the field until the menu appears
  148.   if it is 0 then
  149.     put "You must hold the mouse button down on this button to see the menu"
  150.   end if
  151.   return it
  152. end popmenu
  153.  
  154. function redolist list
  155.   --input list in format "a,b,c,d"
  156.   --output list in format "a;b;c;d"
  157.   -- this just reformats the list for popupmenu to use ";" as the
  158.   -- item separator not ","
  159.   put empty into newlist
  160.   repeat with x=1 to the number of items in list
  161.     put item x of list & ";" after newlist
  162.   end repeat
  163.   return newlist
  164. end redolist
  165.  
  166. on deleteme
  167.   -- this allows an object to be deleted
  168.   if the userlevel is not 5 then
  169.     put the userlevel into temp1
  170.     set the userlevel to 5
  171.   else
  172.     put empty into temp1
  173.   end if
  174.   select me
  175.   domenu "cut field"
  176.   if temp1 is not empty then
  177.     set the userlevel to 5
  178.   end if
  179.   choose browse tool
  180. end deleteme
  181.  
  182. on removecomments
  183. --NOTE:  This is a generally useful script not specifically required for the pop-up --menu functionality. This removes all comments from a script.
  184.   set the cursor to watch
  185.   put the script of me into temp
  186.   repeat with i=1 to the number of lines in temp
  187.     if line i of temp is not empty then
  188.       put " " into ctemp
  189.       put 0 into j
  190.       repeat until ctemp is not " "
  191.         add 1 to j
  192.         put char j of line i of temp into ctemp
  193.       end repeat
  194.       if ctemp is "-" then
  195.         put empty into line i of temp
  196.       end if
  197.     end if
  198.   end repeat
  199.   put removeemptylines (temp) into temp
  200.   set the script of me to temp
  201. end removecomments
  202.  
  203. function getinstanceval instancevarname,classname
  204.   --input:  instance variable name,name of class
  205.   --output:  value for the instance variable of the target
  206.   -- this function gets the value of any instance variable for an
  207.   -- object. This is better than using line numbers because you
  208.   -- don't have to change any scripts if you change the number or order
  209.   -- of instance variables in a class
  210.   put getinstancelist (classname,0) into temp
  211.   put findinstancenum (instancevarname,temp) into tempnum
  212.   put the short name of the target into fieldname
  213.   put line (tempnum+2) of card field fieldname into value
  214.   return value
  215. end getinstanceval
  216.  
  217. on setinstanceval instancevarname,classname,value
  218.   --input:  instance variable name,name of class,value
  219.   --output:  set the instance variable of the target to value
  220.   -- this function sets the value of any instance variable for an
  221.   -- object. This is better than using line numbers because you
  222.   -- don't have to change any scripts if you change the number or order
  223.   -- of instance variables in a class
  224.   put getinstancelist(classname,0) into temp
  225.   put findinstancenum(instancevarname,temp) into tempnum
  226.   put the short name of the target into fieldname
  227.   put value into line (tempnum+2) of card field fieldname
  228. end setinstanceval
  229.  
  230. function findinstancenum instancevarname,list
  231.   --input: instance variable name,list of instance variables in class
  232.   --output: sequence number of this instance variable in the list
  233.   --error:  returns  -1 if name not found
  234.   -- given an instance variable name it and a list of instance names
  235.   -- this returns the item number of the instance name
  236.   put -1 into hit
  237.   repeat with x=1 to the number of items in list
  238.     if item x of list is instancevarname then
  239.       return x
  240.       put 0 into hit
  241.       exit repeat
  242.     end if
  243.   end repeat
  244.   if hit < 0 then
  245.     put "Error:findinstacenum: Instance Name not found"
  246.   end if
  247.   return -1
  248. end findinstancenum
  249.  
  250. function class objectname
  251.   -- this returns the class of an object
  252.   put objectname
  253.   wait 2 seconds
  254.   return line 2 of card field (objectname)
  255. end class
  256.  
  257. function classnumber classname
  258.   -- this returns the item number of the argument in the class list
  259.   global classnames
  260.   put -1 into classnum
  261.   repeat with i=1 to the number of items in classnames
  262.     if classname is item i of classnames then
  263.       put i into classnum
  264.       exit repeat
  265.     end if
  266.   end repeat
  267.   return classnum
  268. end classnumber
  269.  
  270. function getinstancehandlernames iname
  271.   --input  instance name
  272.   --output list of all of the message handlers in the script
  273.   put the script of card field iname into temp
  274.   put scanhandlers(temp) into methodlist
  275.   return methodlist
  276. end getinstancehandlernames
  277.  
  278. function scanhandlers temp
  279.   --input script
  280.   --output list with the names of the message handlers (1/line)
  281.   put 0 into nummethods
  282.   put empty into methodlist
  283.   repeat with i=1 to  number of lines in temp
  284.     if word 1 of line i of temp is "on" then
  285.       add 1 to nummethods
  286.       put word 2 of line i of temp into line nummethods of methodlist
  287.     end if
  288.   end repeat
  289.   return methodlist
  290. end scanhandlers
  291.  
  292. These are the handlers and functions necessary to eliminate the need for the XFCN.  Just replace the handlers with the same name in the above listing by these and add those that don't appear in the above listing and the field will work as a pop-up menu.
  293. on mouseup
  294.   --this is here to override the subsequent mouseup handler which will
  295.   -- be placed in the field containing the popup menu.  If this weren't here
  296.   -- then everytime you click the mouse on the original field the mouseup 
  297.   --  handler for the menu field would be activated.
  298. end mouseup
  299.  
  300. on mouseup
  301.   --this script is placed in the menu field to handle the users selection
  302.   --  the name of the chosen item is returned (to avoid the handler in
  303.   --  the original field (itempicked) from having to know what the
  304.   --  possible choices were.  The cmdflag(which notes whether you're
  305.   --  working with menu choices,instance variable setting,or firing
  306.   --  handlers) is also returned.
  307.   --    The name of the original field is contained in the second to
  308.   --  last line in the menu,while the cmdflag value is contained in the
  309.   --  last line.  Both of which are kept invisible by the selected
  310.   --  sizing for the menu field
  311.   put the clickloc into loc
  312.   put linechoosenfixed (loc) into itemchosen
  313.   put line itemchosen of me into itemchosen
  314.   put  last line of me into cmdflag
  315.   put number of lines in me -1 into temp
  316.   put line temp of me into dest
  317.   send "itempicked itemchosen,cmdflag" to dest
  318.   -- now that we're done with it let's delete the menu field
  319.   --  NOTE:   If you want the menu to hang around just eliminate the next
  320.   --               three lines and included a menu option to eliminate the menu.
  321.   --if the userlevel is not 5 then <==========  To insure menu options available
  322.   --  put the userlevel into temp1 <==========  To insure menu options available
  323.   --  set the userlevel to 5       <==========  To insure menu options available
  324.   -- else                                                  <==========  To insure menu options available
  325.   --   put empty into temp1        <==========  To insure menu options available
  326.   -- end if                                               <==========  To insure menu options available
  327.    select me
  328.   domenu "cut field"
  329.   -- if temp1 is not empty          <==========  To insure menu options available
  330.   --   set the userlevel to temp1   <==========  To insure menu options available
  331.   -- end if                                              <==========  To insure menu options available
  332.   choose browse tool
  333.   --set the userlevel to temp1       <==========  To insure menu options available
  334. end mouseup
  335.  
  336. function linechoosenfixed loc
  337.   --input  x,y location of the mouse click(use the clickloc)
  338.   -- This is a generally useful function which takes the clickloc as
  339.   -- input and finds out which line in a field was clicked on
  340.   put second item of loc into pos
  341.   put pos - the top of the target into pos
  342.   get the textheight of the target
  343.   put it into size
  344.   put trunc(pos/size)+1 into linehit
  345.   return linehit
  346. end linechoosenfixed
  347.  
  348. on mousedown
  349.   --OVERRIDE:POPUP MENU: This is the mousedown handler for the popup
  350.   --menu HC only class.  Holding the mouse down on gives the user defined
  351.   --pop-up menu.  Holding the mouse and option key down gives a menu to
  352.   --change the values of the instance variables. Holding the mouse and
  353.   --shift key down give a menu of the messages (methods) that the
  354.   --instance can handle.
  355.   put 0 into cmdflag
  356.   set the cursor to watch
  357.   -- handle the user setting the value of the instance variables
  358.   if the optionkey is down then
  359.     put 1 into cmdflag
  360.     put instancelistmenu() into list
  361.     -- handlethe user firing the handlers
  362.   else if the shiftkey is down then
  363.     put 2 into cmdflag
  364.     put methodlistmenu() into list
  365.     -- handle the user using the pop-up menu
  366.   else
  367.     put getinstanceval(menuitems,line 2 of me) into list
  368.   end if
  369.   put the clickloc into loc
  370.   -- build and display the pop-up menu
  371.   popHCmenu list,loc,cmdflag
  372. end mousedown
  373.  
  374. on itempicked itemchosen,cmdflag
  375.   --input  name of the menu item selected,the command flag
  376.   -- since the HC version is modeless the handler has to be broken into
  377.   -- two pieces,one to make the menu field and one to handle the message
  378.   -- that the user has picked an item.
  379.   set the cursor to watch
  380.   if itemchosen is not "empty" and itemchosen is not "cancel" then
  381.     -- This section actually implements the menu action.  Note that
  382.     -- we're using the handlemenu and executemenu handlers a little
  383.     -- differently than they were designed for.  They were designed to
  384.     -- make a selection from a list but by sending them a 1 item list
  385.     -- we avoid having to make the list a global variable,or regenerate
  386.     -- it which could be very slow,and we also avoid writing 3 new
  387.     -- handlers for this class
  388.     if cmdflag = 0 then
  389.       handlemenu 1,itemchosen
  390.     else if cmdflag= 1 then
  391.       executeinstancelistmenu 1,itemchosen
  392.     else if cmdflag=2 then
  393.       executemethodmenu 1,itemchosen
  394.     end if
  395.   end if
  396. end itempicked
  397.  
  398. on popHCmenu list,loc,cmdflag
  399.   --input list of menu options,location of menu,command flag
  400.   -- This handler sets up the menu
  401.   --first convert the list into a variable with each item in 1 line
  402.   put listtoline(list) into list
  403.   put the number of lines in list into temp
  404.   --compute the height and width of the field
  405.   -- Note if you change the font size in the makefield handler you
  406.   --  need to change the width and height computations
  407.   put (temp*9)+3 into height
  408.   put the target into line temp+1 of list
  409.   put cmdflag into line temp+2 of list
  410.   put 0 into maxchar
  411.   repeat with i=1 to temp
  412.     if the number of chars in line i of list > maxchar then
  413.       put the number of chars in line i of list into maxchar
  414.     end if
  415.   end repeat
  416.   put maxchar*6 into width
  417.   -- This actually makes the field
  418.   makefield "Popmenu",width,height,loc
  419.   -- Fill the field with the menu options
  420.   put list into card field "Popmenu"
  421.   -- Here find the the beginning and end of the script for the menu field
  422.   --  The menu field has one handler,mouseup,and one function,linechoosen
  423.   --  handleraddress returns the line at which a handler or function
  424.   --  starts and the line at which it ends
  425.   put the script of me into temp
  426.   put handleraddress (temp,"mouseup",3,0) into templine
  427.   put handleraddress (temp,"linechoosenfixed",item 2 of templine,1) into temp1
  428.   put item 1 of templine into tempstart
  429.   put item 2 of temp1 into lastone
  430.   put tempstart - 1 into templine1
  431.   repeat with x=tempstart to lastone
  432.     put line x of temp into line (x-templine1) of temp1
  433.   end repeat
  434.   set the script of card field "Popmenu" to temp1
  435. end popHCmenu
  436.  
  437. on makefield fieldname,xsize,ysize,dest
  438.   -- Input field name,width,height,location
  439.   -- This is a general handler which will make a field with the
  440.   -- default characteristics 
  441.   --if the userlevel is not 5 then              <==========  To insure menu options available
  442.   --  put the userlevel into temp1            <==========  To insure menu options available
  443.   --  set the userlevel to 5                       <==========  To insure menu options available
  444.   -- else                                                  <==========  To insure menu options available
  445.   --   put empty into temp1                     <==========  To insure menu options available
  446.   -- end if                                               <==========  To insure menu options available
  447.   domenu "new field"
  448.   --if temp1 is not empty then               <==========  To insure menu options available
  449.   --  set the userlevel to temp1              <==========  To insure menu options available
  450.   --end if                                               <==========  To insure menu options available
  451.   set the width of card field "" to xsize
  452.   set the height of card field "" to ysize
  453.   set loc of card field "" to dest
  454.   set the textfont of card field "" to "new york"
  455.   set the textsize of card field "" to 9
  456.   set the textstyle of card field "" to "condense"
  457.   set the textheight of card field "" to 9
  458.   set the style of card field "" to "shadow"
  459.   set the textalign of card field "" to "center"
  460.   put the  id of card field "" into fid
  461.   set the locktext of card field "" to true
  462.   set name of  card field "" to fieldname
  463.   set the locktext of card field fieldname to true
  464.   choose browse tool
  465. end makefield
  466.  
  467. function listtoline list
  468.   -- input  a list "c,x,y,35,100,d"
  469.   -- output a variable with item 1 in line 1...item n in line n
  470.   repeat with x=1 to the number of items in list
  471.     put item x of list into line x of temp
  472.   end repeat
  473.   return temp
  474. end listtoline
  475.  
  476. Listing 2
  477.  
  478. WARNING:  The comments we've made about problems with SuperCard™ should be taken with a grain of salt.  we've only been using it a few days and the only documentation we have is the manuals that come with it which are not a full blown course for SuperTalk™.  The scripts shown below do work but there might be other,better,ways to get the same effect.
  479.  
  480. on mouseup
  481.   --this script is placed in the menu field to handle the user's selection
  482.   --  the name of the chosen item is returned(to avoid the handler in
  483.   --  the original field (itempicked) from having to know what the
  484.   --  possible choices were).  The cmdflag(which notes whether you're
  485.   --  working with menu choices,instance variable setting,or firing
  486.   --  handlers) is also returned.
  487.   --    The name of the original field is contained in the second to
  488.   --  last line in the menu,while the cmdflag value is contained in the
  489.   --  last line.  Both of which are kept invisible by the selected
  490.   --  sizing for the menu field
  491.   put the clickloc into loc
  492.   put linechoosenfixed (loc) into itemchosen
  493.   put line itemchosen of me into itemchosen
  494.   put  last line of me into cmdflag
  495.   put number of lines in me -1 into temp
  496.   put line temp of me into dest
  497.   -- These next two lines had to be changed to be compatible with SuperCard™
  498.   put itemchosen & "," & cmdflag into tempstring                                               <============
  499.   send "itempicked" && tempstring to dest                                                          <============
  500.   -- now that we're done with it let's delete the menu field
  501.   -- In HyperCard™ we used doMenu "cut field" in SuperCard™ you have to use
  502.   --  doMenu "cut"
  503.   select me
  504.   domenu "cut"                                                                                                     <============
  505.   choose browse tool
  506. end mouseup
  507.  
  508. on popHCmenu list,loc,cmdflag
  509.   --input list of menu options,location of menu,command flag
  510.   -- This handler sets up the menu
  511.   --first convert the list into a variable with each item in 1 line
  512.   --Note we also changed some of the text sizes in the SuperCard™ version
  513.   put listtoline(list) into list
  514.   put the number of lines in list into temp
  515.   --compute the height and width of the field
  516.   put (temp*10)+3 into height
  517.   put the target into line temp+1 of list
  518.   put cmdflag into line temp+2 of list
  519.   put 0 into maxchar
  520.   repeat with i=1 to temp
  521.     if the number of chars in line i of list > maxchar then
  522.       put the number of chars in line i of list into maxchar
  523.     end if
  524.   end repeat
  525.   put maxchar*8 into width
  526.   -- This actually makes the field
  527.   makefield "Popmenu",width,height,loc
  528.   -- Fill the field with the menu options
  529.   put "Popmenu" into fieldname
  530.   put list into card field fieldname
  531.   --  In SuperCard™ setting these parameters before entering the text didn't seem to   
  532.   --  work so we moved them here.
  533.   set the textfont of card field fieldname to "monaco"
  534.   set the textsize of card field fieldname to 9
  535.   set the textstyle of card field fieldname to "condense"
  536.   set the textheight of card field fieldname to 10
  537.   set the style of card field fieldname to "shadow"
  538.   set the textalign of card field fieldname to "center"
  539.   
  540.   -- Here find the the begining and end of the script for the menu field
  541.   --  The menu field has one handler,mouseup,and one function,linechoosen
  542.   --  handleraddress returns the line at which a handler or function
  543.   --  starts and the line at which it ends
  544.   put the script of me into temp
  545.   put handleraddress (temp,"mouseup",3,0) into templine
  546.   put handleraddress (temp,"linechoosenfixed",item 2 of templine,1) into temp1
  547.   put item 1 of templine into tempstart
  548.   put item 2 of temp1 into lastone
  549.   put tempstart - 1 into templine1
  550.   repeat with x=tempstart to lastone
  551.     put line x of temp into line (x-templine1) of temp1
  552.   end repeat
  553.   set the script of card field "Popmenu" to temp1
  554. end popHCmenu
  555. on makefield fieldname,xsize,ysize,dest
  556.   -- Input field name,width,height,location
  557.   -- This is a general handler which will make a field with the
  558.   -- default characteristics
  559.   -- In HyperCard™ we used doMenu "new field" but SuperCard™ doesn't have
  560.   -- such a menu command.  In SuperCard™ you can create a new field in a script
  561.   -- by using the field rectangle tool
  562.   choose field rectangle tool
  563.   put dest into start
  564.   put item 1 of dest + xsize into item 1 of  finish
  565.   put item 2 of dest + ysize into item 2 of  finish
  566.   drag from start to finish
  567.   -- It seems that you have to go back to the browse tool in SuperCard™ before 
  568.   --  using the field
  569.   choose browse tool
  570.   --  Unlike HyperCard™ SuperCard™ doesn't seem to be able to address fields 
  571.   --   with no nameby using the name "".  But you know that the field you've just
  572.   --    made will always have the highest field number 
  573.   set name of  card field (the number of card fields) to fieldname
  574.   set the locktext of card field fieldname to true
  575.   choose browse tool
  576. end makefield
  577.